﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using sharpCmd.Controls;
using sharpCmd.Controls.Viewers;
using sharpCmd.Dialogs.PanelActions;
using sharpCmd.Classes;

namespace sharpCmd
{
    public partial class MainForm : Form
    {
        #region ctor
        public MainForm()
        {
            InitializeComponent();
            RestorePanels();
        }
        #endregion

        #region fields
        private DirectoryViewPanel ActiveDirectoryViewPanel;
        #endregion fields

        private void MainForm_Load(object sender, EventArgs e)
        {
            ActiveDirectoryViewPanel.DoFocus();
        }

        #region DirectoryViewPanels handling
        private DirectoryViewPanel InactiveDirectoryViewPanel
        {
            get { return dvpLeft == ActiveDirectoryViewPanel ? dvpRight : dvpLeft; }
        }

        void directoryViewPanel_Enter(object sender, EventArgs e)
        {
            ActiveDirectoryViewPanel = sender as DirectoryViewPanel;
            ActivatePanel();
        }

        private void RestorePanels()
        {
            ActiveDirectoryViewPanel = dvpLeft;
            dvpLeft.ViewType = PanelViewType.Full;
            dvpLeft.Path = @"c:\";
            dvpRight.ViewType = PanelViewType.Full;
            dvpRight.Path = @"c:\";
            ActivatePanel();
        }

        private void ActivatePanel()
        {
            ActiveDirectoryViewPanel.Active = true;
            InactiveDirectoryViewPanel.Active = false;
            ActiveDirectoryViewPanel.DoFocus();
        }
        #endregion

        #region layouts
        private void toolStripBottom_Layout(object sender, LayoutEventArgs e)
        {
            //resize buttons
            const int BUTTON_COUNT = 6; // F3,F4,F5,F6,F7,F8
            var usedWidth = toolStripBottom.Items.OfType<ToolStripSeparator>().Sum(p => p.Width + 1);
            int buttonWidth = (toolStripBottom.ClientSize.Width - usedWidth) / BUTTON_COUNT;
            toolStripBottom.Items.OfType<ToolStripButton>().ToList().ForEach(p => p.Width = buttonWidth);
        }

        private void toolStripCmd_Layout(object sender, LayoutEventArgs e)
        {
            const double TEXT_BOX_SIZE = 0.65;
            tbCmd.Width = (int)(toolStripCmd.Width * TEXT_BOX_SIZE);
        }
        #endregion

        #region toolstrip button handlers
        private void packToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Pack");
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void changeAttributesToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void newTabToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ActiveDirectoryViewPanel.OpenNewTab();
        }

        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Options form");
        }

        private void pathToCommandlineToolStripMenuItem_Click(object sender, EventArgs e)
        {
            tbCmd.Text = GetSelectedItemFullName();
        }

        #region Display - sort
        private void nameToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ActiveDirectoryViewPanel.ActiveFileSystemViewer.Sort(sharpCmd.Controls.FileSystemViewers.FileSystemViewer.SortType.Name);
        }

        private void extensionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ActiveDirectoryViewPanel.ActiveFileSystemViewer.Sort(sharpCmd.Controls.FileSystemViewers.FileSystemViewer.SortType.Extension);
        }

        private void dateAndTimeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ActiveDirectoryViewPanel.ActiveFileSystemViewer.Sort(sharpCmd.Controls.FileSystemViewers.FileSystemViewer.SortType.Date);
        }

        private void sizeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ActiveDirectoryViewPanel.ActiveFileSystemViewer.Sort(sharpCmd.Controls.FileSystemViewers.FileSystemViewer.SortType.Size);
        }
        #endregion
        #endregion

        #region Operations
        private void OnView(object sender, EventArgs e)
        {
            ViewerForm viewer = new ViewerForm();
            //TODO set viewer type according to the file type
            viewer.SelectedFile = GetSelectedItemFullName();
            viewer.ShowViewer();
            viewer.Show();
        }

        private void OnEdit(object sender, EventArgs e)
        {
            //TODO 0.20 read editor name from configuration
            Process.Start("notepad.exe", GetSelectedItemFullName());
        }

        private void OnCopy(object sender, EventArgs e)
        {
            //build copy form
            CopyPrepareForm prepForm = new CopyPrepareForm();
            prepForm.TargetDirectory = InactiveDirectoryViewPanel.Path;
            if (prepForm.ShowDialog() != System.Windows.Forms.DialogResult.OK)
                return;
            //get all selected files
            var selectedInfos = GetSelectedItemInfos();
            CopyForm copyForm = new CopyForm();
            copyForm.TargetDirectory = prepForm.TargetDirectory;
            copyForm.Infos = selectedInfos;
            copyForm.Show();
        }

        private void OnMove(object sender, EventArgs e)
        {
            //TODO make copy form with move flag
        }

        private void OnNewDirectory(object sender, EventArgs e)
        {
            Dialogs.Common.CommonTextBoxForm f = new sharpCmd.Dialogs.Common.CommonTextBoxForm();
            if (IsSelectedItem())
                f.Value = GetSelectedItemName();
            if (f.ShowDialog() != DialogResult.OK)
                return;
            Directory.CreateDirectory(Path.Combine(GetSelectedPath(), f.Value));
            OnReload(null, null);
        }

        private void OnDelete(object sender, EventArgs e)
        {

        }

        private void OnReload(object sender, EventArgs e)
        {
            dvpLeft.Reload();
            dvpRight.Reload();
        }
        #endregion

        #region input events
        private void MainForm_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Alt)
            {
                switch (e.KeyCode)
                {
                    case Keys.F1:
                        dvpLeft.DropDownCombobox();
                        break;
                    case Keys.F2:
                        dvpRight.DropDownCombobox();
                        break;
                }
            }
            KeyPress((char)e.KeyValue);
        }

        //TODO implement meaningful cheat codes ;)
        string[] CheatCodes = { "SNAKE" };
        int[] CheatKeyIndexes = { 0 };
        const int CHEAT_COUNT = 1;
        new void KeyPress(char c)
        {
            for (int cheatIdx = 0; cheatIdx < CHEAT_COUNT; cheatIdx++) //for each cheat code
            {
                if (CheatCodes[cheatIdx][CheatKeyIndexes[cheatIdx]] == c)
                { //we have hit the next key in sequence
                    if (++CheatKeyIndexes[cheatIdx] == CheatCodes[cheatIdx].Length) //are we in the end?
                    {
                        if (cheatIdx == 0) //SNAKESNAKE
                        {
                            EasterEggs.SnakeForm snake = new EasterEggs.SnakeForm();
                            snake.ShowDialog();
                        }
                        //reset cheat index so we can enter it next time
                        CheatKeyIndexes[cheatIdx] = 0;
                    }
                }
                else //mistyped, reset cheat index
                    CheatKeyIndexes[cheatIdx] = 0;
            }
        }

        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            switch (msg.Msg)
            {
                case Windows.Events.WM_KEYDOWN:
                    if (msg.WParam.ToInt32() == (int)Keys.Tab)
                    {
                        ToggleActivePanel();
                        return true;
                    }
                    else if (msg.WParam.ToInt32() == (int)Keys.Escape)
                    {
                        ClearCmdTextBox();
                        return true;
                    }
                    break;
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }

        private void ClearCmdTextBox()
        {
            tbCmd.Text = "";
        }

        private void ToggleActivePanel()
        {
            ActiveDirectoryViewPanel = ActiveDirectoryViewPanel == dvpLeft ? dvpRight : dvpLeft;
            ActiveDirectoryViewPanel.DoFocus();
        }
        #endregion input events

        #region selected items retrieval
        private bool IsSelectedItem()
        {
            return ActiveDirectoryViewPanel.ActiveFileSystemViewer.HasSelectedItem;
        }
        private string GetSelectedItemName()
        {
            return ActiveDirectoryViewPanel.ActiveFileSystemViewer.SelectedItem.Name;
        }

        private string GetSelectedItemFullName()
        {
            return ActiveDirectoryViewPanel.ActiveFileSystemViewer.SelectedItem.FullName;
        }

        private string GetSelectedPath()
        {
            return ActiveDirectoryViewPanel.ActiveFileSystemViewer.Path;
        }

        private IEnumerable<FSObjectInfo> GetSelectedItemInfos()
        {
            return ActiveDirectoryViewPanel.ActiveFileSystemViewer.SelectedItemInfos;
        }
        #endregion

        private void tsbCopyNames_Click(object sender, EventArgs e)
        {

        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("SharpCmd - two window file manager\r\n2010 - Juraj Borza\r\nUnder BSD license\r\n\r\nUses GongShell library (http://gong-shell.sourceforge.net/)", "About SharpCmd", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    }
}